//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <regs.h>

.extern myChat

#define szcxinfo 44*4
#define pad     6*4
#define framesize szcxinfo + 0x10

#define sgpr(reg, ptr) \
    sw  $##reg, reg*4(ptr)

// t0 holds value of sp
#define save_context(base,offset)       \
    .set noat;                          \
    .set noreorder;                     \
    sw      $13,13*4+offset(base);      \
    sw      $1, 1*4+offset(base);       \
    mfc0    t5, CP0_STATUS;             \
    sw      $0, 0+offset(base);         \
    sw      t5, 36*4+offset(base);      \
    ori     t5, t5, 0x1;                \
    xori    t5, t5, 0x1;                \
    mtc0    t5, CP0_STATUS;             \
    sw      $5, 5*4+offset(base);       \
    sw      $2, 2*4+offset(base);       \
    sw      $3, 3*4+offset(base);       \
    sw      $4, 4*4+offset(base);       \
    sw      $6, 6*4+offset(base);       \
    sw      $7, 7*4+offset(base);       \
    sw      $8, 8*4+offset(base);       \
    sw      $9, 9*4+offset(base);       \
    sw      $10,10*4+offset(base);      \
    sw      $11,11*4+offset(base);      \
    sw      $12,12*4+offset(base);      \
    sw      $14,14*4+offset(base);      \
    sw      $15,15*4+offset(base);      \
    sw      $16,16*4+offset(base);      \
    sw      $17,17*4+offset(base);      \
    sw      $18,18*4+offset(base);      \
    sw      $19,19*4+offset(base);      \
    sw      $20,20*4+offset(base);      \
    sw      $21,21*4+offset(base);      \
    sw      $22,22*4+offset(base);      \
    sw      $23,23*4+offset(base);      \
    sw      $24,24*4+offset(base);      \
    sw      $25,25*4+offset(base);      \
    sw      $26,26*4+offset(base);      \
    sw      $27,27*4+offset(base);      \
    sw      $28,28*4+offset(base);      \
    move    k0, sp;                     \
    addu    k0, framesize;              \
    sw      k0,29*4+offset(base);    /*save caller sp*/ \
    sw      $30,30*4+offset(base);      \
    sw      $31,31*4+offset(base);      \
    mflo    t1;                         \
    mfhi    t2;                         \
    mfc0    t3, CP0_EPC;                \
    mfc0    t4, CP0_BADVADDR;           \
    mfc0    t8, CP0_CAUSE;              \
    sw      t1, 32*4+offset(base);      \
    sw      t2, 33*4+offset(base);      \
    sw      t3, 34*4+offset(base);      \
    sw      t4, 35*4+offset(base);      \
    sw      t8, 37*4+offset(base);      \
    .set at;                            \
    .set reorder;

#define restore_context(base, offset)   \
    .set noat;                          \
    .set noreorder;                     \
    lw      k1, 36*4+offset(base);      \
    mtc0    k1, CP0_STATUS;             \
    lw      t1, 32*4+offset(base);      \
    lw      t2, 33*4+offset(base);      \
    lw      t3, 34*4+offset(base);      \
    lw      t4, 35*4+offset(base);      \
    lw      t8, 37*4+offset(base);      \
    mtlo    t1;                         \
    mthi    t2;                         \
    mtc0    t3, CP0_EPC;                \
    mtc0    t4, CP0_BADVADDR;           \
    mtc0    t8, CP0_CAUSE;              \
    lw      $0, 0+offset(base);         \
    lw      $1, 1*4+offset(base);       \
    lw      $2, 2*4+offset(base);       \
    lw      $3, 3*4+offset(base);       \
    lw      $4, 4*4+offset(base);       \
    lw      $5, 5*4+offset(base);       \
    lw      $6, 6*4+offset(base);       \
    lw      $7, 7*4+offset(base);       \
    lw      $8, 8*4+offset(base);       \
    lw      $9, 9*4+offset(base);       \
    lw      $10,10*4+offset(base);      \
    lw      $11,11*4+offset(base);      \
    lw      $12,12*4+offset(base);      \
    lw      $13,13*4+offset(base);      \
    lw      $14,14*4+offset(base);      \
    lw      $15,15*4+offset(base);      \
    lw      $16,16*4+offset(base);      \
    lw      $17,17*4+offset(base);      \
    lw      $18,18*4+offset(base);      \
    lw      $19,19*4+offset(base);      \
    lw      $20,20*4+offset(base);      \
    lw      $21,21*4+offset(base);      \
    lw      $22,22*4+offset(base);      \
    lw      $23,23*4+offset(base);      \
    lw      $24,24*4+offset(base);      \
    lw      $25,25*4+offset(base);      \
    lw      $26,26*4+offset(base);      \
    lw      $27,27*4+offset(base);      \
    lw      $28,28*4+offset(base);   /*skip sp restore here*/\
    lw      $30,30*4+offset(base);      \
    lw      $31,31*4+offset(base);      \
    .set at;                            \
    .set reorder;


NESTED_ENTRY(Chat, framesize, ra)
    subu    sp, framesize
    save_context(sp,pad);

    move    a0, sp      // a0=pCxt
    jal     myChat

    restore_context(sp, pad)
    // t0 = moidfied sp(if modified)
    lw      k0,29*4+pad(sp)

    move    sp, k0
    jr      ra
    .set reorder;
END(Chat)
